package io.xiyou.xmq.core;

import javafx.scene.Node;

import java.util.NoSuchElementException;

/**
 * 使用链表来实现队列
 *
 * @ClassName：MyLinkedQueue
 * @Author：西柚
 * @Date：2021/11/5 12:00 下午
 * @Versiion：1.0
 */
public class MyLinkedQueue<E> {
    //容量
    private int capacity;
    //元素个数
    private int size;
    //头节点
    private Node<E> head;
    //尾节点
    private Node<E> tail;

    //节点，保存元素信息，通过next指向下一个节点，形成单链表
    private static class Node<E>{
        E item;
        Node<E> next;//下一个节点

        Node(E e, Node<E> next){
            this.item = e;
            this.next = next;
        }
    }

    //构造函数
    public MyLinkedQueue(int capacity){
        this.capacity = capacity;
    }

    //将元素加入到队列的队尾，如果队列空间不足，抛出异常
    public boolean add(E e) throws Exception{
        //先确定空间是否足够,已经满了就抛出异常
        if(size == capacity){
            throw new Exception("queue full");
        }
        //创建一个新的节点，然后添加到队列尾部
        Node<E> node = new Node<E>(e,null);
        if(size == 0){//如果队列为空
            head = tail = node;
        }else{//如果队列中已经有节点了
            tail.next = node;
            tail = node;
        }
        size ++;
        return true;
    }

    //返回并删除队列头部的元素，如果队列为空，抛出异常
    public E remove() throws NoSuchElementException{
        //判断是否为空,为空则报错
        if(size == 0){
            throw new NoSuchElementException();
        }
        E e = head.item;
        head.item = null; //方便GC
        //将head指向下一个节点
        head = head.next;
        if(head == null){//删除后队列为空，头节点和尾节点都为null
            tail = null;
        }
        size -- ;
        return e ;
    }

    //将元素加入到队尾，如果队列已经满了，返回false
    public boolean offer(E e){
        //先确定空间是否足够,已经满了就返回false
        if(size == capacity){
            return false;
        }
        //创建一个新的节点，然后添加到队列尾部
        Node<E> node = new Node<E>(e,null);
        if(size == 0){//如果队列为空
            head = tail = node;
        }else{//如果队列中已经有节点了
            tail.next = node;
            tail = node;
        }
        size ++;
        return true;
    }

    //返回并删除队列头部的元素，如果队列为空，返回null
    public E poll(){
        //判断是否为空,为空则返回null
        if(size == 0){
            return null;
        }
        E e = head.item;
        head.item = null; //方便GC
        //将head指向下一个节点
        head = head.next;
        if(head == null){//删除后队列为空，头节点和尾节点都为null
            tail = null;
        }
        size -- ;
        return e ;
    }

    //返回队列头部的元素，如果队列为空，抛出异常
    public E element(){
        //判断是否为空,为空则报错
        if(size == 0){
            throw new NoSuchElementException();
        }
        E e = head.item;
        return e;
    }

    //返回队列头部的元素，如果队列为空，返回null
    public E peek(){
        //判断是否为空,为空则返回null
        if(size == 0){
            return null;
        }
        E e = head.item ;
        return e;
    }

}
